import { createInterface } from 'readline'
import { resolve, join } from 'path';
import { parse, build } from 'node-xlsx'
import { readdirSync, existsSync, stat, readdir, writeFileSync, Stats } from 'fs'
import { homedir } from 'os'
import { line, dir, Sheet } from "../../interface/excel";
import { main } from ".";
import { returnLine } from "../custom/custom";
import { formatterDate, oneToTwo } from "./time";



export let sourceMap: line = []
export const dataMap = createDataMap()

// fileDisplay 的变量 arr、timer
const arr: string[] = [];
let timer: any = null;

// 生成行数
let count = 0

// readLine 接管输入输出流
const rl = createInterface({
    input: process.stdin,
    output: process.stdout,
});

// 版本号
export const version = '1.0.1'
/**
 * @Desc 获取目录下所有文件名
 * @name getNames
 */
export function getNames(
    dir: string
): string[] {
    let list: dir[] = readdirSync(dir, { withFileTypes: true })
    return list.map(item => item.name)
}


/**
 * @Desc 根据列代码生成数字下标数组
 * @param arr
 * @returns number[]
 */
export function createTonums(
    arr: string[]
): any[] {
    return arr.map((a: string, idx: number) => {
        return stringTonum(a) - 1
    })
}


/**
 * @Desc 根据列代码返回数字
 * @param a string
 * @returns 
 */
export function stringTonum(
    a: string
): number {
    let str = a.toLowerCase().split("");
    let al = str.length;
    let getCharNumber = function (charx: string) {
        return charx.charCodeAt(0) - 96;
    };
    let numout = 0;
    let charnum = 0;
    for (let i = 0; i < al; i++) {
        charnum = getCharNumber(str[i]);
        numout += charnum * Math.pow(26, al - i - 1);
    };
    return numout;
}

/**
 * 
 * @param date 日期
 * @param sp 分隔符
 * @param timeSp 时间分隔符 
 * @returns 
 */
export function splitDate(
    date: string,
    sp: string,
    timeSp: string = ''
): string {
    let ymd = date.split(' ')[0]
    let time = date.split(' ')[1]
    if (ymd) ymd = ymd.split(sp).map(v => oneToTwo(v)).join('')
    if (time) time = time.split(timeSp || ':').map(v => oneToTwo(v)).join('')
    return `${ymd}${time}`
}

/**
 * 
 * @param file 文件数据
 * @param startIndex 开始的行index
 * @param cols 需要格式化的列index[]
 * @returns 
 */
export function createContent(
    file: Sheet[],
    startIndex: number,
    cols: number[],
    format: string
): Sheet[] {
    let xlsxData: Sheet[] = [
        {
            name: 'Sheet1',
            data: [],
            options: {}
        }
    ]
    if (file && file[0]) {
        // let end: number = file[0].data.length
        let value: line[] = file[0].data
        let outPutValue: line[] = []
        let lineValue: line = []
        let rowCount: number = 0

        sourceMap = value[0]

        value.map((v, idx) => {
            if (idx <= startIndex) {
                return
            }
            // 匹配列key, 自定义规则
            if (v[0]) {
                lineValue = returnLine(sourceMap, v)
                outPutValue.push(lineValue)
                lineValue = []
                rowCount++
            }
        })
        console.log(rowCount, '行')
        count += rowCount
        outPutValue.map((v) => {
            // 日期格式化
            v.map((vv, idx) => {
                if (cols.includes(idx)) {
                    // 是需要格式化的列
                    v[idx] = formatterDate(vv, format)
                }
            })
        })
        xlsxData[0].data = xlsxData[0].data.concat(outPutValue)
    }

    return xlsxData
}

/**
 * @desc 开始
 * @returns Promise 
 */
export function start(): Promise<boolean> {
    let quiz = `
${changeColor(`❗※  Ver.${version}  仅支持拥有1个Sheet页的Excel表格 ※ ❗`, 107)}

${changeColor('主要功能如下:', 108)}
${changeColor('1、处理Excel文件数据', 108)}
${changeColor('2、合并多个Excel变成一个Excel', 108)}
${changeColor('3、处理列数据，目前仅支持日期格式的格式化，将2023-6-14 9:00:10、2023/6/14 9:00:10 格式化为 20230614090010', 108)}
${changeColor('4、处理列数据，1.0.1版本开始支持自定义处理列数据，可以自行到custom/custom.ts中自定义返回值', 108)}

${changeColor('开始 (s/S)', 93)} ${changeColor('过程中重新开始 (r/R)', 95)}  ${changeColor('退出 (q/Q)', 94)} \r\n
${changeColor(`请输入上方对应英文字母并回车确认:`, 96, 4)}`
    return new Promise((rv, rj) => {
        rl.question(quiz, (name: string) => {
            switch (name) {
                case 's':
                    rv(true)
                    break;
                case 'q':
                    process.exit()
                default:
                    rj()
            }
        });
    })
}

/**
 * @desc 提问
 * @param qs 问题描述
 * @param stepNum 步骤index
 * @returns 
 */
export function question(
    qs: string,
    stepNum: number
): Promise<string> {
    let quiz: string = `
${changeColor(`${qs}:\n`, 96, 4)}`
    return new Promise((rv, rj) => {
        rl.question(quiz, (name: string) => {
            name.toLocaleLowerCase()
            if (name === 'r') {
                rj(stepNum)
            }
            rv(name)
        });
    })
}

/**
 * 
 * @param stepNum 步骤index
 * @returns 
 */
export function step(
    stepNum: number
): Promise<string> {
    let steps = [
        '需要合并的文件的文件名关键字 默认 ""',
        '规定输出文件名称 默认 outPut',
        '需要格式化时间的列代码, 多个用逗号隔开, 如: A,E,D',
        '日期格式化自定义，支持 yyyy-mm-dd hh:mm:ss 等等格式'
    ]
    return question(steps[stepNum], stepNum)
}

/**
 * @desc 核心处理数据函数
 * @param startIndex 开始行数
 * @param inPut 数据目录
 * @param outputName 输出文件名
 * @param cols 需要处理的列代码
 * @param findName 匹配的文件名，模糊搜索
 * @param cb callBack， 回调
 * @returns `void`
 */
export function run(
    startIndex: string,
    inPut: string,
    outputName: string,
    cols: number[],
    findName: any,
    format: string,
    cb: Function
): void {
    console.log('火速处理中....')
    let excelData: Sheet[] = [
        {
            name: 'Sheet1',
            data: [
                dataMap
            ],
            options: {

            }
        }
    ]
    if (!findName) {
        console.log('匹配不到""')
        cb()
        return
    }

    fileDisplay(inPut, (filePaths: string[]) => {
        filePaths.forEach(path => {
            if (path.includes(findName)) {
                // 符合条件
                // sheet = parseExcel(path)
                let sheet: Sheet
                sheet = createContent(parseExcel(path), Number(startIndex), cols, format)[0]
                excelData[0].data = excelData[0].data.concat(sheet.data)
            }
        })
        let excel = build(excelData)
        writeFileSync(`${homedir()}\\Desktop\\${outputName}${outputName.includes('.xlsx') ? '' : '.xlsx'}`, excel, 'binary')
        console.log(`结束！生成 ${count} 行，请到桌面领取文件<${outputName}${outputName.includes('.xlsx') ? '' : '.xlsx'}>...`)
        cb()
    })
}

/**
 * 
 * @param input 内容
 * @param color 颜色代码
 * @param style 风格
 * @returns 
 */
export function changeColor(
    input: string,
    color: number = 92,
    style: number = 1
): string {
    return `\x1b[${style};${color}m${input}\x1b[0m`
}

/**
 * @desc 收集所有的文件路径
 * @param url target目录
 * @param cb callBack
 */
export function fileDisplay(url: string, cb: Function) {
    const filePath = resolve(url);
    readdir(filePath, (err, files: any[]) => {
        if (err) return console.error('Error:(spec)', err)
        files.forEach((filename: string) => {
            const filedir: string = join(filePath, filename);
            stat(filedir, (eror, stats: Stats) => {
                if (eror) return console.error('Error:(spec)', err);
                // 是否是文件
                const isFile = stats.isFile();
                // 是否是文件夹
                const isDir = stats.isDirectory();
                if (isFile) {
                    // 这块我自己处理了多余的绝对路径，第一个 replace 是替换掉那个路径，第二个是所有满足\\的直接替换掉
                    arr.push(filedir.replace(__dirname, '').replace(/\\/img, '/'))
                    // 最后打印的就是完整的文件路径了
                    if (timer) clearTimeout(timer)
                    timer = setTimeout(() => cb && cb(arr), 200)
                }
                // 如果是文件夹
                if (isDir) fileDisplay(filedir, cb);
            })
        });
    });
}

/**
 * 
 * @returns 模板的头行
 */
export function createDataMap(): string[] {
    let exist = existsSync(resolve('../Excel/data/模板.xls'))
    let xl
    if (exist) {
        xl = parse(resolve('../Excel/data/模板.xls'))
    } else {
        xl = parse(resolve('../Excel/data/模板.xlsx'))
    }
    return xl[0].data[0]
}
/**
 * 
 * @param path 路径
 * @param option 配置
 * @returns 
 */
export function parseExcel(
    path: string,
    option: object = {}
): Sheet[] {
    return [{ ...parse(path, option)[0], options: {} }]
}

/**
 * 
 * @param argv 参数
 */
export function readArgv(argv: string) {
    switch (argv) {
        case '-v':
            console.log(`v${version}`)
            process.exit()
        case '-help':
        case '-h':
            console.log(`
-v: 版本号   -h: 帮助
            `)
        default:
            main(undefined)
    }
}


/**
 * 
 * @param identityNo 身份证号
 * @returns 年龄 string
 */
export const getAge = (identityNo: string) => {
    const birthYear: number = parseInt(identityNo.substring(6, 10));
    const monthBirth: number = parseInt(identityNo.substring(10, 12));
    const birthDay: number = parseInt(identityNo.substring(12, 14));
    // 获取当前年月日
    const myDate = new Date();
    const nowMonth = myDate.getMonth() + 1;
    const nowDay = myDate.getDay();
    // 计算年龄
    let age: number = myDate.getFullYear() - birthYear;
    if (nowMonth < monthBirth || (nowMonth === monthBirth && nowDay < birthDay)) {
        age -= 1;
    }
    return age.toString()
};

/**
 * @desc 科学计数转数
 * @param num
 */
export function getFullNum(num: number) {
    //处理非数字
    if (isNaN(num)) { return num };
    //处理不需要转换的数字
    var str = '' + num;
    if (!/e/i.test(str)) { return num; };
    return (num).toFixed(18).replace(/\.?0+$/, "");
}